Imports System.drawing

Namespace Overlay
    ''' <summary>
    ''' The AreaOverlay object is used to chart non-stacked area series. 
    ''' Series must be of type jChart.Overlay.Series.AreaSeries
    ''' </summary>
    ''' <remarks></remarks>
    Public Class AreaOverlay
        Inherits OverLayBase

        '---Note: Points in an area region are arranged like this:

        '(5) bottom left
        '(4) top left
        '(3) top middle
        '(2) top right
        '(1) bottom right
        '(0) middle bottom

        ''' <summary>
        ''' oChartDimensions is a jChart.ChartDimensions object that describes the interior of the chart. 
        ''' oXAxis and oYAxis are the X and Y axes that should be used for series belonging to the OverLay object.
        ''' </summary>
        ''' <param name="oChartDimensions"></param>
        ''' <param name="oXAxis"></param>
        ''' <param name="oYAxis"></param>
        ''' <remarks></remarks>
        Public Sub New( _
            ByVal oChartDimensions As ChartDimensions, _
            ByVal oXAxis As XAxis, _
            ByVal oYAxis As YAxis)

            MyBase.New(oChartDimensions, oXAxis, oYAxis)
        End Sub

        Protected Overrides Sub DrawAllSeries(ByRef g As Graphics)
            '---Count all series
            Dim iCountOfSeries_Area As Integer = moSeries.Count

            For Each oSeries As Series.AreaSeries In moSeries
                SeriesToArea(g, oSeries)
            Next
        End Sub

        Private Sub SeriesToArea( _
                 ByRef g As Graphics, _
                 ByVal oSeries As Series.AreaSeries)

            '---Define area values.
            Dim iXPointCount As Integer = moXAxis.XAxisValues.GetUpperBound(0)

            Dim oTopValues(iXPointCount) As Single
            Dim oBottomValues(iXPointCount) As Single

            For iAreaPoint As Integer = 0 To iXPointCount
                '---Bottom of area is top of previous area
                oBottomValues(iAreaPoint) = moYAxis.YAxisValues(0)

                '---Now fill in current area
                oTopValues(iAreaPoint) = oSeries.Values(iAreaPoint)
            Next

            Dim oRegionList As ArrayList = Nothing
            oRegionList = CalculateAreaRegions(g, oSeries, oTopValues, oBottomValues)
            For Each oRegion As RegionArea In oRegionList
                MyBase.AddPolygonRegion(oRegion)
            Next

            Dim iStartPos As Integer = 0
            Dim iEndPos As Integer = 0

            Do
                If iEndPos = oRegionList.Count - 1 OrElse _
                    oRegionList(iEndPos).XValue <> (oRegionList(iEndPos + 1).xvalue - 1) Then

                    Dim oPoints() As Point = MergeRegions(oRegionList, iStartPos, iEndPos)

                    DrawMergedRegion(g, oSeries, oPoints)

                    iStartPos = iEndPos + 1
                End If

                iEndPos = iEndPos + 1
            Loop Until iEndPos = oRegionList.Count
        End Sub

        Private Sub DrawMergedRegion( _
                        ByRef g As Graphics, _
                        ByVal oSeries As Series.AreaSeries, _
                        ByVal oPoints() As Point)

            Dim iOutlineAlpha As Integer
            Dim iInteriorAlpha As Integer

            If oSeries.AlphaValue < 205 Then
                iOutlineAlpha = oSeries.AlphaValue + 50
                iInteriorAlpha = oSeries.AlphaValue
            Else
                iOutlineAlpha = oSeries.AlphaValue
                iInteriorAlpha = oSeries.AlphaValue - 50
            End If

            Dim oInteriorColor As Color = Color.FromArgb(iInteriorAlpha, oSeries.Color.R, oSeries.Color.G, oSeries.Color.B)
            g.FillPolygon(New SolidBrush(oInteriorColor), oPoints)

            g.DrawPolygon(New Pen(Color.Black, 3), oPoints)

            Dim oExteriorColor As Color = Color.FromArgb(iOutlineAlpha, oSeries.Color.R, oSeries.Color.G, oSeries.Color.B)
            g.DrawPolygon(New Pen(oInteriorColor, 2), oPoints)
        End Sub

        Protected Function MergeRegions( _
                                ByVal oRegionList As ArrayList, _
                                ByVal iStartPos As Integer, _
                                ByVal iEndPos As Integer) As Point()

            Dim iCount As Integer = oRegionList.Count * 2
            Dim oPoints(iCount) As Point
            Dim iCurPoint As Integer = 0

            Dim oRegion As RegionArea = oRegionList(iStartPos)

            oPoints(iCurPoint) = oRegion.SeriesPoints(0)
            iCurPoint = iCurPoint + 1

            Dim iRegion As Integer = iStartPos + 1
            If iRegion <= iEndPos Then
                Do While iRegion <= iEndPos
                    oRegion = oRegionList(iRegion)
                    iRegion = iRegion + 1

                    oPoints(iCurPoint) = oRegion.SeriesPoints(0)
                    iCurPoint = iCurPoint + 1

                    oPoints(iCurPoint) = oRegion.SeriesPoints(1)
                    iCurPoint = iCurPoint + 1
                Loop
            Else
                oPoints(iCurPoint) = oRegion.SeriesPoints(1)
                iCurPoint = iCurPoint + 1
            End If

            oPoints(iCurPoint) = oRegion.SeriesPoints(2)
            iCurPoint = iCurPoint + 1

            oRegion = oRegionList(iStartPos)
            oPoints(iCurPoint) = oRegion.SeriesPoints(3)

            If oRegion.SeriesPoints.GetUpperBound(0) = 5 Then
                '---This is a middle region
                oPoints(iCurPoint) = oRegion.SeriesPoints(4)
                iCurPoint = iCurPoint + 1

                oPoints(iCurPoint) = oRegion.SeriesPoints(5)
                'iCurPoint = iCurPoint + 1
            End If

            ReDim Preserve oPoints(iCurPoint)

            Return oPoints
        End Function
    End Class
End Namespace